#ifndef sensor_h
#define sensor_h

#include "Arduino.h"
#include "pins.h"
#include "logger.h"
#include <Wire.h>
#include <Adafruit_MCP4725.h>
#include <Adafruit_ADS1x15.h>
#include <math.h>
#include <stdio.h>
#include "pid.h"

/* dac 0-5v输出 出气阀（比例阀） */

Adafruit_MCP4725 dac;

// 初始化 DAC芯片IIC
void setup_dac()
{
    Wire.setSDA(DAC_SDA); // 设置 SDA 引脚
    Wire.setSCL(DAC_SCL); // 设置 SCL 引脚
    Wire.begin();         // 再调用 begin()
    // 初始化 DAC，默认地址 0x60
    if (!dac.begin(0x60))
    {
        Serial.println("未找到 MCP4725 芯片！");
        // while (1);
    }
    else
    {
        Serial.println("MCP4725 初始化成功！");
    }
}

// 泄气阀释放任务句柄
TaskHandle_t valve2ReleaseTaskHandle = NULL;

// kaidu 0-4095对应0-5v对应阀门开度0-100%
void valve2_open(int kaidu)
{
    // 如果 valve2_release_task 正在运行，且当前调用不是来自该任务，则停止并删除该任务
    TaskHandle_t cur = xTaskGetCurrentTaskHandle();
    if (valve2ReleaseTaskHandle != NULL && valve2ReleaseTaskHandle != cur) {
        vTaskDelete(valve2ReleaseTaskHandle);
        valve2ReleaseTaskHandle = NULL;
        // 可选：打印日志
        Serial.println("valve2_release_task 已被外部设置停止");
    }

    // 限制范围并映射到 DAC 值
    int safe = kaidu;
    if (safe < 0) safe = 0;
    if (safe > 100) safe = 100;
    int dacValue = (safe * 4095) / 100; // 线性映射 0..100 -> 0..4095

    dac.setVoltage(dacValue, false); // false = 不写入 EEPROM
}

// 泄气阀逐渐打开
void valve2_release_task(void *pvParameters)
{
    // 记录当前任务句柄，方便外部删除
    valve2ReleaseTaskHandle = xTaskGetCurrentTaskHandle();

    for (int t = 0; t <= 100; t=t+10) {  // 修改起始值为0
    valve2_open(t);
    vTaskDelay(pdMS_TO_TICKS(10000)); // 10秒
    }

    // 任务结束前清空句柄并自删除
    valve2ReleaseTaskHandle = NULL;
    vTaskDelete(NULL); // 任务结束后自删除
}

/* adc 温度、压力传感器 */
TwoWire I2C_ADC = TwoWire(i2c1, ADC_SDA, ADC_SCL);  // 给 ADC 用

Adafruit_ADS1115 ads;

// 初始化ADC芯片IIC
void setup_adc()
{
    I2C_ADC.setSDA(ADC_SDA);
    I2C_ADC.setSCL(ADC_SCL);
    Wire.begin(); // 再调用 begin()
    if (!ads.begin(0x4A, &I2C_ADC))  // 0x48接gnd，0x49接vdd，0x4A接sda，0x4B接scl
    {
        Serial.println("未找到 ADS1115 芯片！");
        // while (1);
    }
    else
    {
        Serial.println("ADS1115 初始化成功！");
    }
    // The ADC input range (or gain) can be changed via the following
    // functions, but be careful never to exceed VDD +0.3V max, or to
    // exceed the upper and lower limits if you adjust the input range!
    // Setting these values incorrectly may destroy your ADC!
    //                                                                ADS1015  ADS1115
    //                                                                -------  -------
    ads.setGain(GAIN_TWOTHIRDS); // 2/3x gain +/- 6.144V  1 bit = 3mV      0.1875mV (default)
    // ads.setGain(GAIN_ONE);        // 1x gain   +/- 4.096V  1 bit = 2mV      0.125mV
    // ads.setGain(GAIN_TWO);        // 2x gain   +/- 2.048V  1 bit = 1mV      0.0625mV
    // ads.setGain(GAIN_FOUR);       // 4x gain   +/- 1.024V  1 bit = 0.5mV    0.03125mV
    // ads.setGain(GAIN_EIGHT);      // 8x gain   +/- 0.512V  1 bit = 0.25mV   0.015625mV
    // ads.setGain(GAIN_SIXTEEN);    // 16x gain  +/- 0.256V  1 bit = 0.125mV  0.0078125mV
}
// 读取指定通道的ADC值并打印
float adcToPres() {
    int16_t adcValue = ads.readADC_SingleEnded(0);

    // 🌡️ 根据你的 AI-7011 设置修改以下两个值！
    const float PRES_MIN = 0.0;   // 例如：0℃ （对应 4mA / 1V）
    const float PRES_MAX = 20.0; // 例如：1000℃（对应 20mA / 5V）

    // 公式：温度 = PRES_MIN + (电压 - 1.0) * (PRES_MAX - PRES_MIN) / 4.0
    // ADS1115 在 GAIN_TWOTHIRDS 时 LSB = 0.1875 mV = 0.0001875 V
    float voltage = adcValue * 0.0001875;
    float pressure = PRES_MIN + (voltage - 1.0) * (PRES_MAX - PRES_MIN) / 4.0;

    return pressure;
}

float adcToTemp(int channel) {
    int16_t adcValue = ads.readADC_SingleEnded(channel);
    // 🌡️ 根据你的 AI-7011 设置修改以下两个值！
    const float TEMP_MIN = 0.0;   // 例如：0℃ （对应 4mA / 1V）
    const float TEMP_MAX = 1000.0; // 例如：1000℃（对应 20mA / 5V）

    // 公式：温度 = TEMP_MIN + (电压 - 1.0) * (TEMP_MAX - TEMP_MIN) / 4.0
    // ADS1115 在 GAIN_TWOTHIRDS 时 LSB = 0.1875 mV = 0.0001875 V
    float voltage = adcValue * 0.0001875;
    float temperature = TEMP_MIN + (voltage - 1.0) * (TEMP_MAX - TEMP_MIN) / 4.0;
    return temperature;
}

/* ntc热敏电阻 */


/**
 * 将 RP2040 ADC 读数转换为摄氏温度
 * @param adc_value: 12位 ADC 值 (0~4095)
 * @return 温度（摄氏度，float）
 */
float adcToTemp2(uint16_t adc_value) {
    const float VCC = 3.3f;          // 电源电压
    const float R_FIXED = 100000.0f; // 上拉电阻 100kΩ
    const float R0 = 10000.0f;       // NTC 在 25°C 时的阻值
    const float BETA = 3950.0f;      // B值
    const float T0 = 298.15f;        // 25°C 转开尔文

    // 计算 NTC 两端电压
    float v_ntc = (float)adc_value * VCC / 4095.0f;

    // 计算 NTC 电阻值
    float r_ntc = (v_ntc * R_FIXED) / (VCC - v_ntc);

    // 使用 β 参数方程计算温度（开尔文）
    float inv_t = 1.0f / T0 + (1.0f / BETA) * logf(r_ntc / R0);
    float t_k = 1.0f / inv_t;

    // 转换为摄氏度
    float t_c = t_k - 273.15f;

    return t_c;
}

// 全局变量
int targetDuctTemp = 0;
int targetPumpTemp = 0;
int targetReactorTemp = 0;

// 任务句柄
TaskHandle_t ductTempTaskHandle = NULL;
TaskHandle_t pumpTempTaskHandle = NULL;
TaskHandle_t reactorTempTaskHandle = NULL;

// 单独的温度控制函数
void duct_temp_control_task(void *pvParameters) {
    const float TEMP_DEADBAND = 0.5f; // 死区范围 ±0.5℃
    while (1) {
        int adcDuct = analogRead(TempDuct);
        float tempDuctValue = adcToTemp2(adcDuct);
        float error = targetDuctTemp - tempDuctValue;
        if (error > TEMP_DEADBAND) {
            digitalWrite(DuctHeater, HIGH); // 需要加热
        } else if (error < -TEMP_DEADBAND) {
            digitalWrite(DuctHeater, LOW); // 不需要加热
        }
        // 在死区范围内不改变加热器状态
        
        vTaskDelay(pdMS_TO_TICKS(500)); // 0.5秒
    }
}

void pump_temp_control_task(void *pvParameters) {
    const float TEMP_DEADBAND = 0.5f; // 死区范围 ±0.5℃
    while (1) {
        int adcPump = analogRead(TempPump);
        float tempPumpValue = adcToTemp2(adcPump);
        float error = targetPumpTemp - tempPumpValue;
        if (error < -TEMP_DEADBAND) {
            analogWrite(Fan1, 255); // 需要制冷
            digitalWrite(Refrigeration, HIGH);
        } else if (error > TEMP_DEADBAND) {
            digitalWrite(Refrigeration, LOW);
            analogWrite(Fan1, 0); // 不需要制冷
        }
        // 在死区范围内不改变制冷状态
        
        vTaskDelay(pdMS_TO_TICKS(500)); // 0.5秒
    }
}

void reactor_temp_control_task(void *pvParameters) {
    const float TEMP_DEADBAND = 0.5f; // 死区范围 ±0.5℃
    while (1) {
        // float tempReactorValue = adcToTemp(1);
        float tempReactorValue = adcToTemp2(analogRead(TempReactor));
        float error = targetReactorTemp - tempReactorValue;
        if (error > TEMP_DEADBAND) {
            digitalWrite(ReactorHeater, HIGH); // 需要加热
        } else if (error < -TEMP_DEADBAND) {
            digitalWrite(ReactorHeater, LOW); // 不需要加热
        }
        // 在死区范围内不改变加热器状态
        
        vTaskDelay(pdMS_TO_TICKS(500)); // 0.5秒
    }
}

#endif